import { onMounted, onBeforeUnmount } from 'vue'

export interface IframeMessage {
  type: string // 事件类型
  payload?: any // 数据负载
  [key: string]: any
}

type IframeMessageHandler = (payload: any, rawEvent: MessageEvent) => void

interface UseIframeMessengerOptions {
  allowOrigin?: string | string[] // 安全限制：只接受指定来源发来的消息（可为字符串或字符串数组）
  debug?: boolean // 是否输出调试信息
}

/**
 * 基于 window.postMessage 的 iframe 通信封装
 */
export const useIframeMessenger = (options: UseIframeMessengerOptions = {}) => {
  const { allowOrigin = '*', debug = false } = options

  // 消息监听器集合，根据事件类型分发
  const listeners: Map<string, IframeMessageHandler[]> = new Map()

  /**
   * 处理来自 window 的 message 事件
   */
  const handleMessage = (event: MessageEvent) => {
    const origin = event.origin
    const data = event.data

    const isValidOrigin = allowOrigin === '*' || (Array.isArray(allowOrigin) ? allowOrigin.includes(origin) : origin === allowOrigin)

    if (!isValidOrigin) {
      debug && console.warn('[IframeMessenger] 拦截非法来源:', origin)
      return
    }

    if (!data || typeof data !== 'object' || !data.type) {
      debug && console.warn('[IframeMessenger] 无效消息结构:', data)
      return
    }

    debug && console.log('[IframeMessenger] 收到消息:', data, '来自:', origin)

    const handlers = listeners.get(data.type)
    handlers?.forEach((cb) => cb(data.payload, event))
  }

  /**
   * 注册监听器（支持同类型多个监听）
   */
  const on = (type: string, handler: IframeMessageHandler) => {
    if (!listeners.has(type)) {
      listeners.set(type, [])
    }
    listeners.get(type)!.push(handler)
  }

  /**
   * 取消某个事件的监听器
   */
  const off = (type: string, handler: IframeMessageHandler) => {
    const handlers = listeners.get(type)
    if (!handlers) return
    listeners.set(
      type,
      handlers.filter((h) => h !== handler)
    )
  }

  /**
   * 发送消息给父窗口
   */
  const postToParent = (message: IframeMessage, targetOrigin = '*') => {
    if (window.parent) {
      window.parent.postMessage(message, targetOrigin)
      debug && console.log('[IframeMessenger] 发送到父窗口:', message)
    }
  }

  /**
   * 发送消息给 iframe 子窗口
   */
  const postToIframe = (iframeEl: HTMLIFrameElement, message: IframeMessage, targetOrigin = '*') => {
    if (iframeEl?.contentWindow) {
      iframeEl.contentWindow.postMessage(message, targetOrigin)
      debug && console.log('[IframeMessenger] 发送到子窗口:', message)
    }
  }

  /**
   * 生命周期挂载与销毁
   */
  onMounted(() => {
    window.addEventListener('message', handleMessage)
  })

  onBeforeUnmount(() => {
    window.removeEventListener('message', handleMessage)
    listeners.clear()
  })

  return {
    on,
    off,
    postToParent,
    postToIframe
  }
}
